package com.wiscamp.ninechapters.threeparties.mathpix;


import com.google.gson.JsonArray;
import com.google.gson.JsonObject;

import java.io.IOException;
import java.util.concurrent.Callable;

public class Recognition implements Callable<OCRResponse> {
    private static final JsonObject parameters = new JsonObject();

    /**
     * Original parameter explanation: https://docs.mathpix.com/
     * Initialisation of the Recognition class and a JsonObject with unchanged parameters.
     */
    Recognition() {

        // "src" initialises with empty string
        parameters.addProperty("src", "");

        // process both math and text OCR
        var ocrParameters = new JsonArray();
        ocrParameters.add("math");
        ocrParameters.add("text");
        parameters.add("ocr", ocrParameters);

        // force algorithm to consider whole image
        parameters.addProperty("skip_recrop", true);

        // string postprocessing formats
        var formatParameters = new JsonArray();
        // inline math by default
        formatParameters.add("text");
        // block mode math when in doubt
        formatParameters.add("text_display");
        // modified output to improve the visual appearance
        formatParameters.add("latex_styled");
        parameters.add("formats", formatParameters);

        // transforms
        var transformParameters = new JsonArray();
        // omit spaces around LaTeX groups and other places where spaces are superfluous
        transformParameters.add("rm_spaces");
        // convert longdiv to frac as longdiv is not a non-valid LaTeX markup
        transformParameters.add("long_frac");

        // delimiters for math mode
        var mathDelimiterParameters = new JsonArray();
        mathDelimiterParameters.add("\\(");
        mathDelimiterParameters.add("\\)");

        // parameters used for math mode (text)
        var textFormatOptions = new JsonObject();
        textFormatOptions.add("math_delims", mathDelimiterParameters);
        textFormatOptions.add("transforms", transformParameters);

        // delimiters for displaymath mode
        var displayMathDelimiterParameters = new JsonArray();
        displayMathDelimiterParameters.add("\n$$\n ");
        displayMathDelimiterParameters.add(" \n$$\n");

        // parameters used for displaymath mode (text_display)
        var textDisplayFormatOptions = new JsonObject();
        textDisplayFormatOptions.add("displaymath_delims", displayMathDelimiterParameters);
        textDisplayFormatOptions.add("transforms", transformParameters);

        // parameters used for styled LaTeX (latex_styled)
        var transformOptions = new JsonObject();
        transformOptions.add("transforms", transformParameters);

        // format options combined
        var formatOptions = new JsonObject();
        formatOptions.add("text", textFormatOptions);
        formatOptions.add("text_display", textDisplayFormatOptions);
        formatOptions.add("latex_styled", transformOptions);

        parameters.add("format_options", formatOptions);

        // privacy option for not helping to improve
        var privacyOption = new JsonObject();
        privacyOption.addProperty("improve_mathpix", false);

        parameters.add("metadata", privacyOption);

    }

    /**
     * Convert the image to byte[] and encode the image with base64.
     * Replace the "src" value in the pre-initialised parameters JsonObject.
     *
     * @param imageBase64 Image to be recognised.
     * @return if the parameter set is successful.
     */
    Boolean setSrcParameters(String imageBase64) {

        // output stream in byte array
        //ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        // convert javafx.scene.image.Image to java.awt.image.BufferedImage
        //BufferedImage bufferedImage = SwingFXUtils.fromFXImage(image, null);

        try {
            // BufferedImage to byte array output stream
            //ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
            // byte array output stream to byte[]
            //byte[] imageInByte = byteArrayOutputStream.toByteArray();
            // add header of "src"
            var src = "data:image/jpg;base64," + imageBase64;
            // replace original "src" with new encoded value
            parameters.addProperty("src", src);
            return true;
        } catch (Exception e) {
            return false;
        }

    }

    /**
     * Override the supertype method.
     *
     * @return OCR request result.
     * @throws IOException if there is an internet connection error.
     */
    @Override
    public OCRResponse call() throws IOException {
        return OCRRequest.getResult(parameters);
    }
}
